<template>
  <div class="wave-chart-container">
    <!-- 顶部工具栏 -->
    <div class="toolbar">
      <el-button type="primary" @click="showChannelSelector = true">通道选择</el-button>
      <el-button type="info" @click="toggleAutoScale">
        {{ isAutoScale ? "关闭自动缩放" : "开启自动缩放" }}
      </el-button>
      <el-button
        :type="isWaveformAnalysisEnabled ? 'info' : 'success'"
        @click="toggleWaveformAnalysis"
      >
        {{ isWaveformAnalysisEnabled ? "禁用波形分析" : "启用波形分析" }}
      </el-button>
    </div>

    <!-- 波形图主体 -->
    <div class="chart-container" ref="chartContainer">
      <el-scrollbar height="100%">
        <!-- 加载状态 -->
        <div v-if="isLoading" class="loading-container">
          <el-skeleton :rows="3" animated />
        </div>

        <div
          v-else-if="isDataReady && chartOptions"
          class="chart-display-container"
          :style="{ height: `${totalHeight}px` }"
        >
          <!-- 添加搜索索引 aria-hidden="true", 不再隐藏 -->
          <div class="search-index-container">
            <div
              v-for="(channelName, index) in selectedChannelDisplayNames"
              :key="`search-item-${index}`"
              class="search-item"
            >
              {{ channelName }}
            </div>
          </div>

          <!-- 右侧图表渲染区 -->
          <div class="echarts-chart-area">
            <ECharts
              ref="chartRef"
              @chartReady="handleChartReady"
              :options="chartOptions"
              :style="{ height: `${totalHeight}px` }"
              autoresize
            />
          </div>

          <!-- 图表渲染  v-else-if="isDataReady && chartOptions"-->
          <!-- <ECharts :options="chartOptions" :style="{ height: `${totalHeight}px` }" autoresize /> -->
        </div>

        <!-- 无数据状态 -->
        <div v-else class="no-data">
          <el-empty description="暂无数据" />
        </div>
      </el-scrollbar>
    </div>

    <!-- 通道选择抽屉 -->
    <el-drawer v-model="showChannelSelector" title="通道选择" direction="rtl" size="300px">
      <div class="channel-selector">
        <el-input v-model="searchKeyword" placeholder="搜索通道" clearable class="mb-2" />
        <el-scrollbar height="calc(100vh - 200px)">
          <el-checkbox-group v-model="selectedChannels">
            <div v-for="group in filteredChannelGroups" :key="group.name" class="channel-group">
              <div class="group-header">
                <div class="group-header-content">
                  <el-switch
                    :model-value="isGroupSelected(group)"
                    :active-text="group.name"
                    @change="(val) => handleGroupSelect(group, Boolean(val))"
                    class="group-switch"
                  />
                  <el-tag v-if="isGroupIndeterminate(group)" type="info" size="small" class="ml-2">
                    部分选中
                  </el-tag>
                </div>
              </div>
              <div class="group-channels">
                <el-checkbox
                  v-for="channel in group.channels"
                  :key="channel.id"
                  :value="channel.id"
                  :title="channel.name"
                >
                  {{ channel.name }}
                </el-checkbox>
              </div>
            </div>
          </el-checkbox-group>
        </el-scrollbar>
      </div>
    </el-drawer>

    <el-card
      v-if="queryData"
      v-draggable
      class="query-result-card"
      :body-style="{ padding: '10px' }"
      shadow="hover"
    >
      <template #header>
        <div class="card-header">
          <span>{{ queryData.timeLabel }}</span>
        </div>
      </template>
      <el-table :data="queryTableData" size="small" border stripe :show-header="true">
        <el-table-column prop="channel" label="通道" width="130" />
        <el-table-column prop="value" label="值" />
      </el-table>
    </el-card>

    <el-footer height="auto" class="chart-footer">
      <el-row align="middle">
        <el-col :span="24">
          <el-alert
            v-if="rangeInfoResult"
            :title="rangeInfoResult"
            type="info"
            :closable="false"
            show-icon
          />
          <el-alert v-else title="未选择范围" type="info" :closable="false" show-icon />
        </el-col>
      </el-row>
    </el-footer>
  </div>
</template>

<script setup lang="ts">
// import { ref, computed, onMounted, watch } from "vue";
import {
  ElButton,
  ElDrawer,
  ElCheckbox,
  ElCheckboxGroup,
  ElInput,
  ElScrollbar,
} from "element-plus";
import { ComtradeRecord, parseComtradeCfg, loadComtradeSamples } from "@/utils/hmi/comtrade_reader";
import { useDebounceFn } from "@vueuse/core";

// 状态变量
const record = ref<ComtradeRecord | null>(null);
const analogSamples = ref<number[][]>([]);
const digitalSamples = ref<number[][]>([]);
const timeBaseus = ref<number[]>([]);
const showChannelSelector = ref(false);
const searchKeyword = ref("");
const isAutoScale = ref(true);
const isWaveformAnalysisEnabled = ref(false);
const chartContainer = ref<HTMLElement | null>(null);

// 通道分组
interface Channel {
  id: string;
  name: string;
  type: "analog" | "digital";
  data: number[];
}

interface ChannelGroup {
  name: string;
  channels: Channel[];
}

/**
 * 图表网格配置
 * 1. 每个网格高度为 100 px;
 * 2. 网格间距为 0px;
 * 3. 整体网格顶部偏移 50px 、底部偏移 130 px、左偏移 20px、右偏移为 40px;
 */
interface CHART_GRIDS_CONFIG {
  height: number;
  interval: number;
  top_pad: number;
  bot_pad: number;
  left_pad: number;
  right_pad: number;
}

const chart_grids_config = ref<CHART_GRIDS_CONFIG>({
  height: 100,
  interval: 0,
  top_pad: 30,
  bot_pad: 150,
  left_pad: 20,
  right_pad: 40,
});

const channelGroups = computed<ChannelGroup[]>(() => {
  if (!record.value) return [];

  const groups = [
    {
      name: "模拟量通道",
      channels: record.value.analogChannels.map((ch) => ({
        id: ch.id,
        name: `${ch.id} (${ch.unit})`,
        type: "analog" as const,
        data:
          analogSamples.value[record.value!.analogChannels.findIndex((c) => c.id === ch.id)] || [],
      })),
    },
    {
      name: "数字量通道",
      channels: record.value.digitalChannels.map((ch) => ({
        id: ch.id,
        name: ch.id,
        type: "digital" as const,
        data:
          digitalSamples.value[record.value!.digitalChannels.findIndex((c) => c.id === ch.id)] ||
          [],
      })),
    },
  ];
  return groups;
});

// 过滤后的通道组
const filteredChannelGroups = computed<ChannelGroup[]>(() => {
  if (!searchKeyword.value) return channelGroups.value;

  return channelGroups.value
    .map((group) => ({
      ...group,
      channels: group.channels.filter((ch) =>
        ch.name.toLowerCase().includes(searchKeyword.value.toLowerCase())
      ),
    }))
    .filter((group) => group.channels.length > 0);
});

// 选中的通道
const selectedChannels = ref<string[]>([]);

// 添加一个计算属性，用于左侧索引显示通道名称
const selectedChannelDisplayNames = computed(() => {
  return selectedChannels.value.map((id) => {
    const analogChannel = record.value?.analogChannels.find((ch) => ch.id === id);
    if (analogChannel) {
      return `${id} (${analogChannel.unit})`;
    }
    const digitalChannel = record.value?.digitalChannels.find((ch) => ch.id === id);
    if (digitalChannel) {
      return id; // 数字通道只显示ID
    }
    return id; // Fallback，以防万一
  });
});

// --- 核心调整：左右容器引用和滚动同步逻辑 ---
const leftScrollContainer = ref<HTMLElement | null>(null);
const rightScrollContainer = ref<HTMLElement | null>(null);
let isScrollingByScript = false; // 标志位，防止循环滚动

let leftScrollListener: ((e: Event) => void) | null = null;
let rightScrollListener: ((e: Event) => void) | null = null;
// --- 图形分析辅助变量： ---
// 初始三个图形元素的位置信息
// 定义图形元素的数据状态
// 这些值代表在 xAxisData 上的索引或近似索引
interface GraphicElementsData {
  selectLineX: number; // 查询线的数据坐标 (xAxisData 索引)
  rangeLeftX: number; // 范围左边界的数据坐标 (xAxisData 索引)
  rangeRightX: number; // 范围右边界的数据坐标 (xAxisData 索引)
  totalHeight: number; // 所有通道的高度之和
  firstTop: number; // 第一个通道的顶部位置
}

interface DragGraphicElementsTempData {
  dragStartXData: number;
  dragEndXData: number;
  dragStartPixelX: number;
  dragEndPixelX: number;
}

// 图形元素的数据状态，初始值可以设置为 xAxisData 的某个索引
const graphicElementsState = reactive<GraphicElementsData>({
  selectLineX: 40, // 初始在第一个数据点
  rangeLeftX: 100, // 初始在数据点索引 2
  rangeRightX: 200, // 初始在数据点索引 4
  totalHeight: 0,
  firstTop: 0,
});

const dragTempState = ref<DragGraphicElementsTempData>({
  dragStartPixelX: 0,
  dragEndPixelX: 0,
  dragStartXData: 0,
  dragEndXData: 0,
});

// 卡片拖拽指令
// 自定义拖动指令
const vDraggable: Directive = {
  mounted(el) {
    el.style.position = "absolute";
    el.style.zIndex = "1000";

    // 初始位置设置在右上角
    el.style.top = "70px";
    el.style.right = "20px";

    const header = el.querySelector(".el-card__header");
    if (!header) return;

    header.style.cursor = "move";
    header.onmousedown = (e: MouseEvent) => {
      // 阻止文本选择
      e.preventDefault();

      // 获取初始位置
      const startX = e.clientX;
      const startY = e.clientY;
      const startLeft = el.offsetLeft;
      const startTop = el.offsetTop;

      // 鼠标移动处理函数
      const handleMouseMove = (moveEvent: MouseEvent) => {
        const deltaX = moveEvent.clientX - startX;
        const deltaY = moveEvent.clientY - startY;

        el.style.left = startLeft + deltaX + "px";
        el.style.top = startTop + deltaY + "px";
      };

      // 鼠标释放处理函数
      const handleMouseUp = () => {
        document.removeEventListener("mousemove", handleMouseMove);
        document.removeEventListener("mouseup", handleMouseUp);
      };

      // 添加事件监听
      document.addEventListener("mousemove", handleMouseMove);
      document.addEventListener("mouseup", handleMouseUp);
    };
  },
};

const handleScroll = (event: Event, source: "left" | "right") => {
  if (isScrollingByScript) return;

  isScrollingByScript = true;
  const currentScrollTop = (event.target as HTMLElement).scrollTop;

  if (source === "left" && rightScrollContainer.value) {
    rightScrollContainer.value.scrollTop = currentScrollTop;
  } else if (source === "right" && leftScrollContainer.value) {
    leftScrollContainer.value.scrollTop = currentScrollTop;
  }

  // 使用 nextTick 或 requestAnimationFrame 来重置标志，确保DOM更新完成后再允许下一次滚动
  nextTick(() => {
    isScrollingByScript = false;
  });
};

// 通道选择相关方法
const isGroupSelected = (group: ChannelGroup): boolean => {
  return group.channels.every((ch) => selectedChannels.value.includes(ch.id));
};

const isGroupIndeterminate = (group: ChannelGroup): boolean => {
  const selectedCount = group.channels.filter((ch) =>
    selectedChannels.value.includes(ch.id)
  ).length;
  return selectedCount > 0 && selectedCount < group.channels.length;
};

const handleGroupSelect = (group: ChannelGroup, checked: boolean): void => {
  const channelIds = group.channels.map((ch) => ch.id);
  if (checked) {
    selectedChannels.value = [...new Set([...selectedChannels.value, ...channelIds])];
  } else {
    selectedChannels.value = selectedChannels.value.filter((id) => !channelIds.includes(id));
  }
};

// 自动缩放相关
const toggleAutoScale = () => {
  isAutoScale.value = !isAutoScale.value;
};

// 波形分析功能开关
const toggleWaveformAnalysis = () => {
  isWaveformAnalysisEnabled.value = !isWaveformAnalysisEnabled.value;

  if (isWaveformAnalysisEnabled.value) {
    // 启用波形分析功能
    if (chart_instance.value) {
      addGraphicsAnalysis(chart_instance.value);
    }
  } else {
    // 禁用波形分析功能
    if (chart_instance.value) {
      removeGraphicsAnalysis(chart_instance.value);
    }
  }
};

// 定义移除图层元素的函数
// // 这个函数需要接收 ECharts 实例作为参数
const removeGraphicsAnalysis = (echartsInstance: any) => {
  if (!echartsInstance) {
    console.error("removeGraphicsAnalysis: ECharts instance is not provided.");
    return;
  }

  try {
    console.log("正在执行 removeGraphicsAnalysis...");
    // 移除所有的图形元素
    echartsInstance.setOption({
      graphic: {
        elements: [],
      },
    });
    graphicsAdded.value = false;
    console.log("removeGraphicsAnalysis 执行完成。");
    // 清除查询数据和范围信息
    queryData.value = null;
    rangeInfoResult.value = "";
  } catch (error) {
    console.error("removeGraphicsAnalysis: Error removing graphics:", error);
  }
};

// y轴标签-可检索的计算样式对象
// const chartContainerStyle = computed(() => ({
//   "--search-item-height": `${100 + 0}px`,
// }));

// 计算图表总高度
const totalHeight = computed(() => {
  const selectedCount = selectedChannels.value.length;
  const baseHeight = chart_grids_config.value.height; // 减小每个图表的基础高度
  const spacing = chart_grids_config.value.interval; // 减小图表之间的间距
  return (
    selectedCount * (baseHeight + spacing) +
    chart_grids_config.value.top_pad +
    chart_grids_config.value.bot_pad
  ); // 减小额外空间
});

// 计算图表总高度
// const totalHeight = computed(() => {
//   const selectedCount = selectedChannels.value.length;
//   if (selectedCount === 0) return 0; // 没有选中通道时高度为0

//   const chartUnitHeight = 100; // 每个子图表的高度
//   const chartSpacing = 10; // 每个子图表之间的间距

//   // 总高度 = 子图表数量 * (单个图表高度 + 间距) + 底部额外空间 (例如X轴标签和一些padding)
//   // 这里的 150 对应 grid bottom 的值，确保最底部的图表也能完全显示其X轴
//   return selectedCount * chartUnitHeight + (selectedCount - 1) * chartSpacing + 150;
// });

const chartOptions = ref<any>(null);
const isLoading = ref(false);
const isDataReady = ref(false);

const chartRef = ref(null);
const chart_instance = ref(null);
const graphicsAdded = ref(false);
// 当前活跃的 ECharts 实例
let currentEChartsInstance = null;
const queryData = ref<{
  timeLabel: string;
  channelLabel: string[];
  channelValues: number[];
} | null>(null);

const queryTableData = computed(() => {
  if (!queryData.value) return [];
  if (!queryData.value.channelValues) return [];

  return queryData.value.channelValues.map((value, index) => ({
    channel: queryData.value?.channelLabel[index] || `通道 ${index + 1}`,
    value,
  }));
});

const rangeInfoResult = ref<string>("");

// // 显示查询线对应的数据点值
const displaySelectLineData = (xData: number) => {
  try {
    const roundedX = Math.round(xData); // 四舍五入到最近的整数索引
    console.log("displaySelectLineData: ", xData, roundedX);
    if (roundedX < 0 || roundedX >= timeBaseus.value.length) {
      // queryResult.value = "数据点超出范围";
      queryData.value = null;
      return;
    }

    const timeLabel = String(timeBaseus.value[roundedX]);
    // let result = `查询点 (${timeLabel}):\n`;
    // chartData.seriesData.forEach((series, index) => {
    //   result += `通道 ${index + 1}: ${series[roundedX]}\n`;
    // });
    // queryResult.value = result;
    // 存储通道名称
    // 存储所有通道的值为数字数组
    // 查询出所有选择的模拟通道的名称，根据 record 和 selectedChannels
    const analogChannels = record.value?.analogChannels || [];
    const selectedAnalogNames = [];
    const selectedAnalogValues = [];
    // 遍历模拟通道，并检查其ID是否在selectedChannels中
    for (const channel of analogChannels) {
      if (selectedChannels.value.includes(channel.id)) {
        selectedAnalogNames.push(channel.id);
        // console.log("channel: ", channel, "analogsamples: ", analogSamples.value);
        selectedAnalogValues.push(analogSamples.value[channel.index - 1][roundedX]);
        // const ana_channel_idx = analog_channel_id_to_idx_map.value.get(channel.id);
        // if(ana_channel_idx !== undefined)
        //   selectedAnalogValues.push(analogSamples.value[ana_channel_idx]);
      }
    }

    const digitalChannels = record.value?.digitalChannels || [];
    const selectedDigitalNames = [];
    const selectedDigitalValues = [];
    for (const channel of digitalChannels) {
      if (selectedChannels.value.includes(channel.id)) {
        selectedDigitalNames.push(channel.id);
        selectedDigitalValues.push(digitalSamples.value[channel.index - 1][roundedX]);
      }
    }

    // 判断长度是否一致
    if (
      selectedAnalogNames.length !== selectedAnalogValues.length ||
      selectedDigitalNames.length !== selectedDigitalValues.length
    ) {
      console.error("数据长度不一致");
      return;
    }

    const channelLabel = [...selectedAnalogNames, ...selectedDigitalNames];
    const channelValues = [...selectedAnalogValues, ...selectedDigitalValues];

    // const channelValues: number[] = chartData.seriesData.map((series) => series[roundedX]);
    // 更新查询数据对象
    queryData.value = {
      timeLabel,
      channelLabel,
      channelValues,
    };
  } catch (error) {
    console.error("Error in displaySelectLineData:", error);
  }
};

/**
 * 获取查询线的样式配置
 * @param xData 查询线的X轴数据索引
 * @returns 查询线的ECharts配置选项
 */
const getSelectLineOption = (xData: number): EChartsOption => {
  if (!chart_instance.value) throw new Error("Chart not initialized");
  try {
    // 获取网格信息
    // const { totalHeight, firstGridTop } = getGridsInfo();
    const totalHeight = chart_grids_config.value.height * selectedChannels.value.length;
    const firstGridTop = chart_grids_config.value.top_pad;

    // 将数据坐标转换为像素坐标
    const pixelX = chart_instance.value.convertToPixel({ xAxisIndex: 0 }, xData) as number;

    return {
      graphic: {
        elements: [
          {
            id: "selectLine",
            $action: "merge",
            type: "rect",
            shape: { width: 4, height: totalHeight },
            style: { fill: "rgba(0,128,255,0.8)", stroke: "none", opacity: 1 },
            x: pixelX - 2, // 居中
            y: firstGridTop,
            z: 100,
            bounding: "raw",
            silent: false,
            cursor: "ew-resize",
            draggable: true,
          },
        ],
      },
    };
  } catch (error) {
    console.error("Error in getSelectLineOption:", error);
    return {};
  }
};

/**
 * 获取范围线和范围区域的样式配置
 * @param leftXData 左边界线的X轴数据索引
 * @param rightXData 右边界线的X轴数据索引
 * @returns 范围线和范围区域的ECharts配置选项
 */
const getRangeLineOption = (leftXData: number, rightXData: number): EChartsOption => {
  if (!chart_instance.value) throw new Error("Chart not initialized");

  try {
    // 获取网格信息
    // const { totalHeight, firstGridTop } = getGridsInfo();
    const totalHeight = chart_grids_config.value.height * selectedChannels.value.length;
    const firstGridTop = chart_grids_config.value.top_pad;

    // 转换为像素坐标
    const leftPixelX = chart_instance.value.convertToPixel({ xAxisIndex: 0 }, leftXData) as number;
    const rightPixelX = chart_instance.value.convertToPixel(
      { xAxisIndex: 0 },
      rightXData
    ) as number;

    // 计算范围区域的宽度和左侧位置
    const width = Math.abs(rightPixelX - leftPixelX);
    const left = Math.min(leftPixelX, rightPixelX);

    // 计算范围信息文本的位置（居中）
    const centerX = (leftPixelX + rightPixelX) / 2;

    // 获取范围内的点数
    const startIndex = Math.min(Math.round(leftXData), Math.round(rightXData));
    const endIndex = Math.max(Math.round(leftXData), Math.round(rightXData));
    const dataCount = Math.max(0, endIndex - startIndex + 1); // 包含首尾

    return {
      graphic: {
        elements: [
          // 左边界线
          {
            id: "rangeLeftLine",
            $action: "merge",
            type: "rect",
            shape: { width: 4, height: totalHeight },
            style: { fill: "rgba(255,190,0,0.8)", stroke: "none", opacity: 1 },
            x: leftPixelX - 2, // 居中
            y: firstGridTop,
            z: 100,
            bounding: "raw",
            silent: false,
            cursor: "ew-resize",
            draggable: true,
          },
          // 右边界线
          {
            id: "rangeRightLine",
            $action: "merge",
            type: "rect",
            shape: { width: 4, height: totalHeight },
            style: { fill: "rgba(255,190,0,0.8)", stroke: "none", opacity: 1 },
            x: rightPixelX - 2, // 居中
            y: firstGridTop,
            z: 100,
            bounding: "raw",
            silent: false,
            cursor: "ew-resize",
            draggable: true,
          },
          // 范围区域矩形
          {
            id: "areaRect",
            $action: "merge",
            type: "rect",
            shape: { width: width, height: totalHeight },
            style: { fill: "rgba(255,190,0,0.1)", stroke: "none" }, // 半透明黄色
            x: left,
            y: firstGridTop,
            z: 90, // 在线条下方
            silent: true, // 不可拖拽
          },
          // 范围信息文本
          {
            id: "areaInfoText",
            $action: "merge",
            type: "text",
            style: {
              text: `点数: ${dataCount}`,
              fill: "#333",
              fontSize: 12,
              textAlign: "center",
              textVerticalAlign: "bottom", // 文本在指定y轴位置的下方
            },
            x: centerX,
            y: firstGridTop - 5, // 放置在范围区域上方
            z: 110,
            silent: true,
            invisible: false, // 默认可见
          },
        ],
      },
    };
  } catch (error) {
    console.error(error);
    return {};
  }
};

// 更新范围信息文本
const updateRangeInfoText = () => {
  try {
    const { rangeLeftX, rangeRightX } = graphicElementsState;
    const startIndex = Math.min(Math.round(rangeLeftX), Math.round(rangeRightX));
    const endIndex = Math.max(Math.round(rangeLeftX), Math.round(rangeRightX));

    // 计算包含的数据点数量
    const dataCount = Math.max(0, endIndex - startIndex + 1);

    // 更新文本内容
    rangeInfoResult.value = `范围包含点数: ${dataCount}, 时间范围: ${0.25 * (dataCount - 1)} ms`;

    // 同时更新 graphic 元素中的文本内容和位置
    if (chart_instance.value) {
      // const { firstGridTop } = getGridsInfo(); // 重新获取位置信息
      chart_instance.value.setOption({
        graphic: {
          elements: [
            createAreaInfoText(
              graphicElementsState.rangeLeftX,
              graphicElementsState.rangeRightX,
              chart_grids_config.value.top_pad,
              true // 确保文本可见
            ),
          ],
        },
      });
    }
  } catch (error) {
    console.error("updateRangeInfoText error: ", error);
  }
};

const onGraphicDragStart = (id: string) => {
  if (!chart_instance.value) {
    return;
  }

  try {
    // 获取当前被拖拽线的数据坐标，作为拖拽的起始点
    if (id === "selectLine") {
      dragTempState.value.dragStartXData = graphicElementsState.selectLineX;
    } else if (id === "rangeLeftLine") {
      dragTempState.value.dragStartXData = graphicElementsState.rangeLeftX;
    } else if (id === "rangeRightLine") {
      dragTempState.value.dragStartXData = graphicElementsState.rangeRightX;
    }

    // 获取拖拽开始时的鼠标像素坐标
    if (chart_instance.value) {
      dragTempState.value.dragStartPixelX = chart_instance.value.convertToPixel(
        { gridIndex: 0 },
        dragTempState.value.dragStartXData
      ) as number;
    }

    // 可选：拖拽开始时改变线条样式，例如加粗或变色
    chart_instance.value.setOption({
      graphic: {
        elements: [
          {
            id: id,
            style: {
              stroke: "red", // 拖拽时变红
              lineWidth: 4, // 拖拽时加粗
            },
          },
        ],
      },
    });
  } catch (error) {
    console.error(error);
  }
};

const onGraphicDragEnd = (e: ElementEvent, id: string) => {
  if (!chart_instance.value) return;
  try {
    // 恢复线条样式
    chart_instance.value?.setOption({
      graphic: {
        elements: [
          {
            id: id,
            style: {
              stroke: "none", // 移除红色边框
              fill: "rgba(0,128,255,0.8)", // 恢复蓝色
              lineWidth: 2, // 恢复默认宽度
            },
          },
        ],
      },
    });

    // 获取拖拽结束时的鼠标像素坐标
    dragTempState.value.dragEndPixelX = e.offsetX;
    // 将像素坐标转换为数据索引
    dragTempState.value.dragEndXData = chart_instance.value.convertFromPixel({ gridIndex: 0 }, [
      dragTempState.value.dragEndPixelX,
      0,
    ])[0];
    // 限制在有效范围内并四舍五入到最近的索引
    const clampedDataX = Math.max(
      0,
      Math.min(Math.round(dragTempState.value.dragEndXData), timeBaseus.value.length - 1)
    );

    // 根据拖拽结束时的位置，显示相应的信息
    if (id === "selectLine") {
      graphicElementsState.selectLineX = clampedDataX;
      displaySelectLineData(clampedDataX);
      // 重新设置 selectLine 的样式 option
      const selectLineStyle = getSelectLineOption(clampedDataX);
      chart_instance.value.setOption(selectLineStyle);
    } else if (id === "rangeLeftLine") {
      graphicElementsState.rangeLeftX = clampedDataX;
      // 重新设置范围线的样式
      const rangeLineOption = getRangeLineOption(
        graphicElementsState.rangeLeftX,
        graphicElementsState.rangeRightX
      );
      chart_instance.value.setOption(rangeLineOption);
      updateRangeInfoText();
    } else if (id === "rangeRightLine") {
      graphicElementsState.rangeRightX = clampedDataX;
      // 重新设置范围线的样式
      const rangeLineOption = getRangeLineOption(
        graphicElementsState.rangeLeftX,
        graphicElementsState.rangeRightX
      );
      chart_instance.value.setOption(rangeLineOption);
      updateRangeInfoText();
    }

    // 清除拖拽状态
    // dragStartXData = null;
    // dragStartPixelX = null;
    dragTempState.value.dragStartPixelX = 0;
    dragTempState.value.dragStartXData = 0;
  } catch (error) {
    console.error(error);
  }
};

const createRect = (
  xData: number, // 数据坐标 (xAxisData 索引)
  height: number, // 像素高度，将跨越所有 grid
  top: number, // 像素 top，从第一个 grid 的 top 开始
  id: string
): GraphicComponentOption => {
  if (!chart_instance.value) return {};

  try {
    // 将数据坐标 xData 转换为第一个 grid (xAxisIndex: 0) 的像素坐标
    // 因为这些线是共享的，我们选择第一个 xAxisIndex 进行坐标转换
    const pixelX = chart_instance.value.convertToPixel({ xAxisIndex: 0 }, xData) as number;

    // 根据线条ID设置不同的颜色
    let fillColor = "rgba(0,128,255,0.8)"; // 默认蓝色线（查询线）
    if (id === "rangeLeftLine" || id === "rangeRightLine") {
      fillColor = "rgba(255,190,0,0.8)"; // 黄色线（范围边界线）
    }

    return {
      type: "rect",
      id: id, // ID 保持唯一
      $action: "merge", // 使用 merge 更新
      shape: { width: 4, height: height }, // 线的宽度
      style: { fill: fillColor, stroke: "none", opacity: 1 }, // 蓝色线
      x: pixelX - 2, // 居中
      y: top,
      z: 100,
      bounding: "raw",
      silent: false,
      cursor: "ew-resize",
      draggable: true,
      // 拖拽事件处理器
      // ondrag: dragHandler,
      ondragstart: () => onGraphicDragStart(id),
      ondragend: (e: ElementEvent) => onGraphicDragEnd(e, id),
    } as any;
  } catch (error) {
    console.error(error);
    return {};
  }
};

// 创建范围区域矩形
const createAreaRect = (
  x1Data: number,
  x2Data: number, // 数据坐标 (xAxisData 索引)
  height: number,
  top: number // 像素高度和 top
): GraphicRectOption => {
  if (!chart_instance.value) return {};

  try {
    // 转换为像素坐标 (使用第一个 grid 的 xAxis)
    const pixelX1 = chart_instance.value.convertToPixel({ xAxisIndex: 0 }, x1Data) as number;
    const pixelX2 = chart_instance.value.convertToPixel({ xAxisIndex: 0 }, x2Data) as number;

    // 确保宽度为正，left 为较小的 x 坐标
    const width = Math.abs(pixelX2 - pixelX1);
    const left = Math.min(pixelX1, pixelX2);

    return {
      type: "rect",
      id: `areaRect`,
      $action: "merge",
      shape: { width: width - 10, height: height },
      style: { fill: "rgba(183,81,5,0.1)", stroke: "none" }, // 半透明黄色
      x: left + 5,
      y: top,
      z: 90, // 在线条下方
      silent: true, // 不可拖拽
    };
  } catch (error) {
    console.error("createAreaRect error: ", error);
    return {};
  }
};

// 创建范围信息文本
const createAreaInfoText = (
  x1Data: number,
  x2Data: number, // 数据坐标 (xAxisData 索引)
  top: number, // 像素 top
  isVisible: boolean = true // 默认可见
): GraphicComponentTextOption => {
  if (!chart_instance.value) return {};

  try {
    // 将数据坐标转换为像素坐标，用于定位文本
    const pixelX1 = chart_instance.value.convertToPixel({ xAxisIndex: 0 }, x1Data) as number;
    const pixelX2 = chart_instance.value.convertToPixel({ xAxisIndex: 0 }, x2Data) as number;
    const centerX = (pixelX1 + pixelX2) / 2;

    // 获取范围内的点数
    const startIndex = Math.min(Math.round(x1Data), Math.round(x2Data));
    const endIndex = Math.max(Math.round(x1Data), Math.round(x2Data));
    const dataCount = Math.max(0, endIndex - startIndex + 1); // 包含首尾

    return {
      type: "text",
      id: `areaInfoText`,
      $action: "merge",
      style: {
        text: rangeInfoResult.value,
        fill: "#333",
        fontSize: 12,
      },
      x: centerX,
      y: top - 5, // 放置在范围区域上方
      z: 110,
      silent: true,
      invisible: !isVisible, // 控制可见性
    };
  } catch (error) {
    console.error("createAreaInfoText error: ", error);
    return {};
  }
};

// 使用防抖优化图表更新
const debouncedUpdateChartOption = useDebounceFn(() => {
  if (!record.value || !selectedChannels.value.length) {
    chartOptions.value = null;
    return;
  }

  isLoading.value = true;

  // 使用 nextTick 确保在下一个渲染周期更新
  nextTick(() => {
    // 定义一组更和谐、平静舒适的颜色系列
    try {
      // const harmoniousCalmingColors = [
      //   "#FF4500", // 鲜橙红
      //   "#00BFFF", // 深天蓝
      //   "#32CD32", // 酸橙绿
      //   "#FF1493", // 深粉红
      //   "#FFD700", // 金色
      //   "#8A2BE2", // 紫罗兰
      //   "#00FF7F", // 春绿
      //   "#FF6347", // 番茄红
      //   "#1E90FF", // 道奇蓝
      //   "#FF00FF", // 洋红
      // ];
      const selectedChannelsData = selectedChannels.value
        .map((id) => {
          const analogChannel = record.value!.analogChannels.find((ch) => ch.id === id);
          const digitalChannel = record.value!.digitalChannels.find((ch) => ch.id === id);

          if (analogChannel) {
            const idx = record.value!.analogChannels.findIndex((ch) => ch.id === id);
            return {
              id,
              name: `${id} (${analogChannel.unit})`,
              type: "analog" as const,
              data: analogSamples.value[idx] || [],
              channel: analogChannel,
            };
          } else if (digitalChannel) {
            const idx = record.value!.digitalChannels.findIndex((ch) => ch.id === id);
            return {
              id,
              name: id,
              type: "digital" as const,
              data: digitalSamples.value[idx] || [],
              channel: digitalChannel,
            };
          }
          return null;
        })
        .filter((item): item is NonNullable<typeof item> => item !== null);

      // 生成网格配置
      const grids = selectedChannelsData.map((_, idx) => ({
        left: chart_grids_config.value.left_pad, // 略微增加左边距，为Y轴标签留出空间
        right: chart_grids_config.value.right_pad, // 略微增加右边距
        height: chart_grids_config.value.height,
        bottom:
          chart_grids_config.value.bot_pad +
          (selectedChannelsData.length - idx - 1) * chart_grids_config.value.height,
      }));

      // 生成X轴配置
      const xAxis = selectedChannelsData.map((_, idx) => ({
        type: "category",
        data: timeBaseus.value,
        gridIndex: idx,
        axisLabel: {
          // show: idx === selectedChannelsData.length - 1, // 仅在最底部的X轴显示标签
          show: false, // 隐藏X轴标签
          color: "#ffffff", // 标签颜色为白色，与深色背景形成良好对比
          // interval: Math.floor(timeBaseus.value.length / 10) - 1, // 如果数据量大，可以启用间隔显示
        },
        axisTick: {
          // show: idx === selectedChannelsData.length - 1, // 仅在最底部的X轴显示刻度
          show: false, // 隐藏X轴刻度
          lineStyle: { color: "#ffffff" }, // 刻度线颜色
        },
        axisLine: {
          // show: idx === selectedChannelsData.length - 1, // 仅在最底部的X轴显示轴线
          show: false, // 隐藏X轴轴线
          lineStyle: { color: "#ffffff" }, // 轴线颜色
        },
        splitLine: {
          // show: true, // 显示垂直网格线
          show: false, // 隐藏垂直网格线
          lineStyle: { type: "solid", color: "rgba(255,255,255,0.05)" }, // 非常浅的白色，保持轻微可见
        },
      }));

      // 生成Y轴配置
      const yAxis = selectedChannelsData.map((channel, idx) => {
        const data = channel.data;
        const min = isAutoScale.value ? Math.min(...data) : channel.type === "digital" ? 0 : -10;
        const max = isAutoScale.value ? Math.max(...data) : channel.type === "digital" ? 1 : 10;

        return {
          type: "value",
          gridIndex: idx,
          min,
          max,
          // axisLabel: {
          //   show: true, // Y轴标签全部显示，便于识别各通道的数值范围
          //   color: "#ffffff", // 标签颜色为白色
          //   formatter: function (value) {
          //     return value.toFixed(2); // 格式化数值，显示两位小数，使标签更整洁
          //   },
          // },
          axisLabel: {
            show: false,
          },
          axisLine: {
            show: true, // 显示Y轴线
            lineStyle: { color: "#ffffff" }, // Y轴线颜色
          },
          axisTick: {
            show: true, // 显示Y轴刻度
            lineStyle: { color: "#ffffff" }, // Y轴刻度颜色
          },
          splitLine: {
            show: false, // 显示水平网格线
            lineStyle: { type: "solid", color: "rgba(255,255,255,0.1)" }, // 略深于垂直网格线，帮助读取数值
          },
        };
      });

      // 生成系列配置
      const series = selectedChannelsData.map((channel, idx) => ({
        id: "serie" + idx,
        z: 1,
        name: channel.name,
        type: "line",
        data: channel.data,
        xAxisIndex: idx,
        yAxisIndex: idx,
        showSymbol: false,
        sampling: "average",
        lineStyle: {
          width: 2.5, // 保持较粗的线条宽度，使其在深色背景下更突出
          // color: harmoniousCalmingColors[idx % harmoniousCalmingColors.length], // 使用新的和谐平静颜色
        },
        step: channel.type === "digital" ? "end" : undefined, // 数字信号使用阶梯图,
      }));

      chartOptions.value = {
        backgroundColor: "#8395b4", // 设置整个图表的背景色为灰色
        tooltip: {
          trigger: "axis",
          axisPointer: {
            type: "none",
            lineStyle: {
              color: "#ffffff", // 提示框的十字指示线颜色为白色
              width: 1,
              type: "dashed",
            },
          },
          // 可选：如果默认的tooltip文字颜色在深色背景下不清晰，可以调整
          textStyle: {
            color: "#333", // 通常tooltip背景是浅色，所以深色文字即可
          },
        },
        grid: grids,
        xAxis,
        yAxis,
        series,
        animation: false, // 禁用动画，适用于实时数据或大量数据
      };

      isLoading.value = false;
      isDataReady.value = true;
    } catch (error) {
      console.error("Error in debouncedUpdateChart:", error);
    }
  });
}, 300);

// 监听 selectedChannels 变化，更新 chartOptions
watch(
  [selectedChannels, isAutoScale, isWaveformAnalysisEnabled],
  () => {
    debouncedUpdateChartOption();
  },
  { immediate: true }
);

// ------------------------------------------------------------------------------------------------
// 核心逻辑：确保 ECharts 实例可用后执行 addGraphicsAnalysis
// ------------------------------------------------------------------------------------------------

// 定义添加图层元素的函数
// 这个函数需要接收 ECharts 实例作为参数
const addGraphicsAnalysis = (echartsInstance: any) => {
  if (!echartsInstance) {
    console.error("addGraphicsAnalysis: ECharts instance is not provided.");
    return;
  }
  console.log("isWaveformAnalysisEnabled", isWaveformAnalysisEnabled.value);
  if (!isWaveformAnalysisEnabled.value) {
    return;
  }

  try {
    chart_instance.value = echartsInstance;
    console.log("正在执行 addGraphicsAnalysis...");
    // 为图表元素配置项设置初始值
    graphicElementsState.totalHeight = selectedChannels.value.length * 100;
    graphicElementsState.firstTop = chart_grids_config.value.top_pad;
    // 示例：在图表上添加一个文本图形元素
    echartsInstance.setOption({
      graphic: {
        elements: [
          // 查询线
          createRect(
            graphicElementsState.selectLineX,
            graphicElementsState.totalHeight,
            graphicElementsState.firstTop,
            "selectLine"
          ),
          // 范围左边界线
          createRect(
            graphicElementsState.rangeLeftX,
            graphicElementsState.totalHeight,
            graphicElementsState.firstTop,
            "rangeLeftLine"
          ),
          // 范围右边界线
          createRect(
            graphicElementsState.rangeRightX,
            graphicElementsState.totalHeight,
            graphicElementsState.firstTop,
            "rangeRightLine"
          ),
          // 范围区域 (在左边界和右边界之间)
          createAreaRect(
            graphicElementsState.rangeLeftX,
            graphicElementsState.rangeRightX,
            graphicElementsState.totalHeight,
            graphicElementsState.firstTop
          ),
          // 范围信息文本，初始不可见
          createAreaInfoText(
            graphicElementsState.rangeLeftX,
            graphicElementsState.rangeRightX,
            graphicElementsState.firstTop,
            false
          ),
        ],
      },
    });
    graphicsAdded.value = true; // 标记已添加
    console.log("addGraphicsAnalysis 执行完成。");
    displaySelectLineData(graphicElementsState.selectLineX);
    console.log("displaySelectLineData 执行完成。");
  } catch (error) {
    console.error("addGraphicsAnalysis: Error adding graphics:", error);
  }
};

// ------------------------------------------------------------------------------------------------
// 核心逻辑：监听子组件发出的 chartReady 事件
// ------------------------------------------------------------------------------------------------

// 当子组件 ECharts 实例准备就绪时触发
const handleChartReady = (instance: any) => {
  console.log("父组件: 接收到 chartReady 事件，ECharts 实例已可用。");
  currentEChartsInstance = instance; // 保存实例引用
  addGraphicsAnalysis(currentEChartsInstance);
};

// 加载数据
onMounted(async () => {
  // 确保 DOM 元素已经准备好
  if (!chartContainer.value) {
    console.warn("Chart container not found");
    return;
  }

  try {
    isLoading.value = true;
    isDataReady.value = false;

    if (leftScrollContainer.value) {
      leftScrollListener = (e) => handleScroll(e, "left");
      leftScrollContainer.value.addEventListener("scroll", leftScrollListener);
    }
    if (rightScrollContainer.value) {
      rightScrollListener = (e) => handleScroll(e, "right");
      rightScrollContainer.value.addEventListener("scroll", rightScrollListener);
    }

    const cfgRes = await fetch("/wave-data/JMXZLP215_RCD_00020_20250613_090622_822_f.cfg");
    const buffer = await cfgRes.arrayBuffer();
    // @ts-ignore
    const decoder = new TextDecoder("gb2312");
    const cfgContent = decoder.decode(buffer);
    record.value = parseComtradeCfg(cfgContent);

    const datRes = await fetch("/wave-data/JMXZLP215_RCD_00020_20250613_090622_822_f.dat");
    const datBuffer = await datRes.arrayBuffer();
    const result = loadComtradeSamples(datBuffer, record.value);

    analogSamples.value = result.analogSamples;
    digitalSamples.value = result.digitalSamples;
    timeBaseus.value = result.timeBaseus;

    // 默认选择所有通道
    // if (record.value) {
    //   selectedChannels.value = [
    //     ...record.value.analogChannels.map((ch) => ch.id),
    //     ...record.value.digitalChannels.map((ch) => ch.id),
    //   ];
    // }
    // debug 选择 2 个通道
    if (record.value) {
      selectedChannels.value = [
        record.value.analogChannels[0].id,
        record.value.analogChannels[1].id,
      ];
    }

    isLoading.value = false;
    isDataReady.value = true;
  } catch (error) {
    console.error("加载波形数据失败:", error);
    isLoading.value = false;
  }
});

onBeforeUnmount(() => {
  if (leftScrollContainer.value && leftScrollListener) {
    leftScrollContainer.value.removeEventListener("scroll", leftScrollListener);
  }
  if (rightScrollContainer.value && rightScrollListener) {
    rightScrollContainer.value.removeEventListener("scroll", rightScrollListener);
  }
});
</script>

<style scoped lang="scss">
// 确保父容器有高度，使 chart-display-container 的 height: 100% 生效
html,
body,
#app {
  height: 100%;
  margin: 0;
  padding: 0;
  overflow: hidden; // 防止整个页面滚动
}

.wave-chart-container {
  height: 100%; // 占据父容器的全部高度
  padding: 10px;
  display: flex;
  flex-direction: column; // 工具栏和图表区域垂直堆叠
  // background-color: #333d4e; // 整个容器的背景色，与 chart-container 保持一致
  color: #e0e0e0; // 默认字体颜色
}

.toolbar {
  padding: 10px 20px;
  // background-color: #2c3440; // 工具栏背景色
  color: #e0e0e0; // 工具栏字体颜色
  display: flex;
  gap: 10px; // 按钮间距
  align-items: center;
}

.chart-container {
  flex: 1;
  // overflow: hidden;
  position: relative;

  // 针对 el-scrollbar 内部生成的滚动条进行样式定制
  // 这里的 :deep() 是为了穿透组件作用域，应用到 el-scrollbar 的内部元素
  :deep(.el-scrollbar__wrap) {
    // 默认 el-scrollbar__wrap 会有 overflow: auto; 这里不额外设置
    // 关键是定制滚动条的视觉样式

    // 自定义滚动条样式 (针对 WebKit 浏览器: Chrome, Safari, Edge)
    &::-webkit-scrollbar {
      width: 8px; // 垂直滚动条宽度
      height: 8px; // 水平滚动条高度 (如果需要水平滚动)
    }

    &::-webkit-scrollbar-track {
      background: rgba(255, 255, 255, 0.1); // 轨道背景色，浅色半透明
      border-radius: 4px;
    }

    &::-webkit-scrollbar-thumb {
      background-color: rgba(255, 255, 255, 0.5); // 滑块颜色，浅色半透明
      border-radius: 4px;
      &:hover {
        background-color: rgba(255, 255, 255, 0.7); // 鼠标悬停时更亮
      }
    }

    // 针对 Firefox 浏览器
    scrollbar-width: thin; // 可以是 auto, thin, none。thin 可以让滚动条更细
    scrollbar-color: rgba(255, 255, 255, 0.5) rgba(255, 255, 255, 0.1); // thumb track color
  }
}

.loading-container {
  padding: 20px;
}

.no-data {
  display: flex;
  justify-content: center;
  align-items: center;
  height: 200px;
}

.channel-selector {
  padding: 16px;

  .mb-2 {
    margin-bottom: 8px;
  }
}

.channel-group {
  margin-bottom: 16px;

  .group-header {
    margin-bottom: 8px;
    font-weight: bold;
    display: flex; // 确保 switch 和 tag 在一行
    align-items: center;
  }
  .group-header-content {
    display: flex;
    align-items: center;
    width: 100%;
  }
  .group-switch {
    flex-grow: 1; // 让 switch 占据更多空间
  }

  .group-channels {
    padding-left: 24px;

    .el-checkbox {
      display: block;
      margin-bottom: 4px;
    }
  }
}

/* Flex 容器，其高度由 totalHeight 决定 */
.chart-display-container {
  display: flex;
  width: 100%; /* 确保容器占满可用宽度 */
  background-color: #8395b4; // 波形图主体背景色
}

.search-index-container {
  flex-shrink: 0; /* 防止此容器在空间不足时收缩 */
  width: 150px; /* 根据你的标签内容调整此宽度，确保能容纳最长的标签 */
  padding: 10px 5px; /* 上下内边距 */
  // 限制最大高度，防止标签列表过长，并允许其内部滚动
  // max-height: calc(100vh - 250px); /* 示例：视口高度减去头部和底部留白 */
  // overflow-y: auto; /* 如果标签过多，允许垂直滚动 */
  // 确保标签文字在深色背景下可见
  color: #f0f4f7;
  font-size: 14px;
  // 禁止 y 滚动
  overflow-y: hidden;
  // background-color: #8395b4;
  // 隐藏 search-index-container 自身的滚动条
  scrollbar-width: none; /* Firefox */
  &::-webkit-scrollbar {
    display: none; /* Chrome, Safari, Edge */
  }

  .search-item {
    height: 100px; // 每行文本固定 100px 高
    line-height: 100px; // 使文本垂直居中
    padding: 0 5px; // 左右内边距
    align-items: center;
    justify-content: center;
    border-bottom: 1px solid rgba(255, 255, 255, 0.1); // 分隔线
    cursor: pointer;
    white-space: nowrap; // 防止文本换行
    overflow: hidden; // 隐藏溢出部分
    text-overflow: ellipsis; // 显示省略号
    color: #e0e0e0;
    &:last-child {
      border-bottom: none; // 最后一行没有下边框
    }

    &:hover {
      background-color: rgba(255, 255, 255, 0.05); // 鼠标悬停效果
    }
  }
}

.echarts-chart-area {
  flex: 1; // 占据剩余所有空间
  height: 100%; // 占据父容器的全部高度
  background-color: #8395b4; // 图表区域背景色，与 ECharts 背景色一致
  border-radius: 8px;
  overflow-y: hidden; // 隐藏垂直滚动条

  box-sizing: border-box; // 边框盒模型
  padding: 0 0; // 顶部和底部留白，左右无留白
  position: relative; // 如果 ECharts 内部定位需要

  scrollbar-width: none; /* Firefox */
  &::-webkit-scrollbar {
    display: none; /* Chrome, Safari, Edge */
  }
}

/* 查询结果卡片样式 */
.query-result-card {
  width: 260px;
  max-width: 80vw;
  max-height: 80vh;
  overflow: auto;
}

.card-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  font-weight: bold;
  color: #0066cc;
}

.query-content {
  font-size: 13px;
  line-height: 1.5;
}

.query-line {
  margin-bottom: 4px;
}

.channel-label {
  font-weight: 500;
}

.channel-value {
  margin-left: 4px;
  font-weight: bold;
  color: #d14;
}

/* 底部信息栏样式 */
.chart-footer {
  position: fixed; /* or 'fixed' if you want it absolutely fixed to viewport */
  bottom: 0;
  background-color: #f5f5f5;
  border-top: 1px solid #e0e0e0;
  padding: 8px 15px;
}
</style>
